package com.meiyuetao.myt.sale.entity;

import java.math.BigDecimal;
import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.UniqueConstraint;

import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.web.json.DateJsonSerializer;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Formula;
import org.hibernate.envers.NotAudited;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.meiyuetao.myt.core.entity.MytBaseEntity;
import com.meiyuetao.myt.md.entity.Commodity;
import com.meiyuetao.myt.stock.entity.StorageLocation;

@MetaData("销售（发货）单明细")
@Entity
@Table(name = "myt_sale_delivery_detail", uniqueConstraints = @UniqueConstraint(columnNames = { "order_sid", "commodity_sid", "is_gift", "storage_location_sid", "batch_no" }))
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SaleDeliveryDetail extends MytBaseEntity {
    private static final long serialVersionUID = 1L;
    @MetaData(value = "子凭证号")
    private String subVoucher;
    @MetaData("销售（发货）单")
    private SaleDelivery saleDelivery;
    @MetaData("商品")
    private Commodity commodity;
    @MetaData("价格")
    private BigDecimal price;
    @MetaData("数量")
    private BigDecimal quantity;
    @MetaData("单位")
    private String measureUnit;
    @MetaData("原价金额")
    private BigDecimal originalAmount;
    @MetaData("折扣率(%)")
    private BigDecimal discountRate;
    @MetaData("折扣额")
    private BigDecimal discountAmount;
    @MetaData("税率(%)")
    private BigDecimal taxRate;
    @MetaData("税额")
    private BigDecimal taxAmount;
    @MetaData("折后金额 ")
    private BigDecimal amount;
    @MetaData("成本单价")
    private BigDecimal costPrice = BigDecimal.ZERO;
    @MetaData("成本金额")
    private BigDecimal costAmount = BigDecimal.ZERO;
    @MetaData("库存地")
    private StorageLocation storageLocation;
    @MetaData("是否赠品")
    private Boolean gift = Boolean.FALSE;
    @MetaData("含税总金额")
    private BigDecimal commodityAndTaxAmount = BigDecimal.ZERO;
    @MetaData("关联销售订单行项商品")
    private BoxOrderDetailCommodity boxOrderDetailCommodity;

    @MetaData(value = "销售单锁定数量", comments = "仅当对象关联boxOrderDetailCommodity，对象扣减boxOrderDetailCommodity上的锁定库存量")
    private BigDecimal salingLockedQuantity = BigDecimal.ZERO;
    @MetaData("退货数量")
    private BigDecimal returnQuantity = BigDecimal.ZERO;

    @MetaData(value = "毛利率")
    private BigDecimal profitRate;

    @MetaData(value = "毛利额")
    private BigDecimal profitAmount;
    @MetaData(value = "批次号")
    private String batchNo;
    @MetaData(value = "过期时间")
    private Date expireDate;
    @MetaData("关联退换货单行项")
    private SaleReturnDetail saleReturnDetail;

    @Column(length = 128, nullable = true)
    @JsonProperty
    public String getSubVoucher() {
        return subVoucher;
    }

    public void setSubVoucher(String subVoucher) {
        this.subVoucher = subVoucher;
    }

    @ManyToOne
    @JoinColumn(name = "order_sid", nullable = false)
    @JsonProperty
    public SaleDelivery getSaleDelivery() {
        return saleDelivery;
    }

    public void setSaleDelivery(SaleDelivery saleDelivery) {
        this.saleDelivery = saleDelivery;
    }

    @OneToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "commodity_sid", nullable = false)
    @JsonProperty
    public Commodity getCommodity() {
        return commodity;
    }

    public void setCommodity(Commodity commodity) {
        this.commodity = commodity;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getCostPrice() {
        return costPrice;
    }

    public void setCostPrice(BigDecimal costPrice) {
        this.costPrice = costPrice;
    }

    @ManyToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "storage_location_sid")
    @NotAudited
    @JsonProperty
    public StorageLocation getStorageLocation() {
        return storageLocation;
    }

    public void setStorageLocation(StorageLocation storageLocation) {
        this.storageLocation = storageLocation;
    }

    @JsonProperty
    @Column(name = "is_gift")
    public Boolean getGift() {
        return gift;
    }

    public void setGift(Boolean gift) {
        this.gift = gift;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getQuantity() {
        return quantity;
    }

    public void setQuantity(BigDecimal quantity) {
        this.quantity = quantity;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getOriginalAmount() {
        return originalAmount;
    }

    public void setOriginalAmount(BigDecimal originalAmount) {
        this.originalAmount = originalAmount;
    }

    @Column(precision = 18, scale = 2, nullable = true)
    @JsonProperty
    public BigDecimal getDiscountRate() {
        return discountRate;
    }

    public void setDiscountRate(BigDecimal discountRate) {
        this.discountRate = discountRate;
    }

    @Column(precision = 18, scale = 2, nullable = true)
    @JsonProperty
    public BigDecimal getDiscountAmount() {
        return discountAmount;
    }

    public void setDiscountAmount(BigDecimal discountAmount) {
        this.discountAmount = discountAmount;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    @Column(precision = 18, scale = 2)
    @JsonProperty
    public BigDecimal getTaxRate() {
        return taxRate;
    }

    public void setTaxRate(BigDecimal taxRate) {
        this.taxRate = taxRate;
    }

    @Column(precision = 18, scale = 2)
    @JsonProperty
    public BigDecimal getTaxAmount() {
        return taxAmount;
    }

    public void setTaxAmount(BigDecimal taxAmount) {
        this.taxAmount = taxAmount;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getCostAmount() {
        return costAmount;
    }

    public void setCostAmount(BigDecimal costAmount) {
        this.costAmount = costAmount;
    }

    @JsonProperty
    public String getMeasureUnit() {
        return measureUnit;
    }

    public void setMeasureUnit(String measureUnit) {
        this.measureUnit = measureUnit;
    }

    @Column(precision = 18, scale = 2, nullable = false)
    @JsonProperty
    public BigDecimal getCommodityAndTaxAmount() {
        return commodityAndTaxAmount;
    }

    public void setCommodityAndTaxAmount(BigDecimal commodityAndTaxAmount) {
        this.commodityAndTaxAmount = commodityAndTaxAmount;
    }

    @ManyToOne
    @JoinColumn(name = "ORDER_DETAIL_COMMODITY_SID", nullable = true)
    @JsonProperty
    public BoxOrderDetailCommodity getBoxOrderDetailCommodity() {
        return boxOrderDetailCommodity;
    }

    public void setBoxOrderDetailCommodity(BoxOrderDetailCommodity boxOrderDetailCommodity) {
        this.boxOrderDetailCommodity = boxOrderDetailCommodity;
    }

    public BigDecimal getSalingLockedQuantity() {
        return salingLockedQuantity;
    }

    public void setSalingLockedQuantity(BigDecimal salingLockedQuantity) {
        this.salingLockedQuantity = salingLockedQuantity;
    }

    @JsonProperty
    public BigDecimal getReturnQuantity() {
        return returnQuantity;
    }

    public void setReturnQuantity(BigDecimal returnQuantity) {
        this.returnQuantity = returnQuantity;
    }

    @Formula("(case when amount=0 then -1 else (amount - cost_amount)/amount end)")
    @JsonProperty
    @NotAudited
    public BigDecimal getProfitRate() {
        return profitRate;
    }

    public void setProfitRate(BigDecimal profitRate) {
        this.profitRate = profitRate;
    }

    @Formula("(amount - cost_amount)")
    @JsonProperty
    @NotAudited
    public BigDecimal getProfitAmount() {
        return profitAmount;
    }

    public void setProfitAmount(BigDecimal profitAmount) {
        this.profitAmount = profitAmount;
    }

    @Transient
    @JsonProperty
    public BigDecimal getDiscountPrice() {
        return amount.divide(quantity, 2, BigDecimal.ROUND_HALF_DOWN);
    }

    @JsonProperty
    @Column(name = "batch_no")
    public String getBatchNo() {
        return batchNo;
    }

    public void setBatchNo(String batchNo) {
        this.batchNo = batchNo;
    }

    @JsonSerialize(using = DateJsonSerializer.class)
    @JsonProperty
    public Date getExpireDate() {
        return expireDate;
    }

    public void setExpireDate(Date expireDate) {
        this.expireDate = expireDate;
    }

    @OneToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "sale_return_detail_sid")
    public SaleReturnDetail getSaleReturnDetail() {
        return saleReturnDetail;
    }

    public void setSaleReturnDetail(SaleReturnDetail saleReturnDetail) {
        this.saleReturnDetail = saleReturnDetail;
    }

}